// 版权所有2012 Go作者。版权所有。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

package png

// intSize为32或64。
const intSize = 32 << (^uint(0) >> 63)

func abs(x int) int {
	// m:=-1如果x<0。m:=0，否则。
	m := x >> (intSize - 1)

	// 在二的补码表示法中，任何数字（最小的除外）的负数
	// 都可以通过翻转所有位并加1来计算。这比带分支的
	// 代码快。
	// 见《黑客的喜悦》，第2-4节。
	return (x ^ m) - m
}

// paeth根据PNG规范实现paeth过滤器功能。这是PNG规范中示例代码的优化版本。例如，示例代码以：
func paeth(a, b, c uint8) uint8 {
	// p:=int（a）+int（b）-int（c）
	// pa:=abs（p-int（a））开头
	// 但是优化后的表单使用的算术运算更少：
	// pa:=int（b）-int（c）
	// pa=abs（pa）
	pc := int(c)
	pa := int(b) - pc
	pb := int(a) - pc
	pc = abs(pa + pb)
	pa = abs(pa)
	pb = abs(pb)
	if pa <= pb && pa <= pc {
		return a
	} else if pb <= pc {
		return b
	}
	return c
}

// filterPaeth将Paeth过滤器应用于cdat切片。
// cdat是当前行的数据，pdat是前一行的数据。
func filterPaeth(cdat, pdat []byte, bytesPerPixel int) {
	var a, b, c, pa, pb, pc int
	for i := 0; i < bytesPerPixel; i++ {
		a, c = 0, 0
		for j := i; j < len(cdat); j += bytesPerPixel {
			b = int(pdat[j])
			pa = b - c
			pb = a - c
			pc = abs(pa + pb)
			pa = abs(pa)
			pb = abs(pb)
			if pa <= pb && pa <= pc {
				// 无操作
			} else if pb <= pc {
				a = b
			} else {
				a = c
			}
			a += int(cdat[j])
			a &= 0xff
			cdat[j] = uint8(a)
			c = b
		}
	}
}
